#include "h3dLuaBindings.h"
#include "Horde3DUtils.h"
#include "lua.hpp"
#include "../core/Logger.h"
#include "../core/LuaUtils.h"

void H3DLuaBindings::pushStaticFuncs(lua_State* L)
{
	// push the actual functions
	static const struct luaL_Reg mylib [] = {
		{"DumpMessages", li_h3dutDumpMessages},
		{"SetNodeTransform", li_h3dSetNodeTransform},
		{"GetVersionString", li_h3dGetVersionString},
		{"CheckExtension", li_h3dCheckExtension},
		{"GetError", li_h3dGetError},
		{"Init", li_h3dInit},
		{"Release", li_h3dRelease},
		{"SetupViewport", li_h3dSetupViewport},
		{"Render", li_h3dRender},
		{"FinalizeFrame", li_h3dFinalizeFrame},
		{"Clear", li_h3dClear},
		{"ShowOverlay", li_h3dShowOverlay},
		{"ClearOverlays", li_h3dClearOverlays},
		{"GetResType", li_h3dGetResType},
		{"GetResName", li_h3dGetResName},
		{"GetNextResource", li_h3dGetNextResource},
		{"FindResource", li_h3dFindResource},
		{"AddResource", li_h3dAddResource},
		{"CloneResource", li_h3dCloneResource},
		{"RemoveResource", li_h3dRemoveResource},
		{"IsResLoaded", li_h3dIsResLoaded},
		{"UnloadResource", li_h3dUnloadResource},
		{"GetResElemCount", li_h3dGetResElemCount},
		{"FindResElem", li_h3dFindResElem},
		{"GetResParamI", li_h3dGetResParamI},
		{"SetResParamI", li_h3dSetResParamI},
		{"GetResParamF", li_h3dGetResParamF},
		{"SetResParamF", li_h3dSetResParamF},
		{"GetResParamStr", li_h3dGetResParamStr},
		{"SetResParamStr", li_h3dSetResParamStr},
		{"QueryUnloadedResource", li_h3dQueryUnloadedResource},
		{"ReleaseUnusedResources", li_h3dReleaseUnusedResources},
		{"CreateTexture", li_h3dCreateTexture},
		{"SetShaderPreambles", li_h3dSetShaderPreambles},
		{"SetMaterialUniform", li_h3dSetMaterialUniform},
		{"GetNodeType", li_h3dGetNodeType},
		{"GetNodeParent", li_h3dGetNodeParent},
		{"SetNodeParent", li_h3dSetNodeParent},
		{"GetNodeChild", li_h3dGetNodeChild},
		{"AddNodes", li_h3dAddNodes},
		{"RemoveNode", li_h3dRemoveNode},
		{"SetNodeActivation", li_h3dSetNodeActivation},
		{"CheckNodeTransFlag", li_h3dCheckNodeTransFlag},
		{"GetNodeParamI", li_h3dGetNodeParamI},
		{"SetNodeParamI", li_h3dSetNodeParamI},
		{"GetNodeParamF", li_h3dGetNodeParamF},
		{"SetNodeParamF", li_h3dSetNodeParamF},
		{"GetNodeParamStr", li_h3dGetNodeParamStr},
		{"SetNodeParamStr", li_h3dSetNodeParamStr},
		{"FindNodes", li_h3dFindNodes},
		{"GetNodeFindResult", li_h3dGetNodeFindResult},
		{"CastRay", li_h3dCastRay},
		{"CheckNodeVisibility", li_h3dCheckNodeVisibility},
		{"AddGroupNode", li_h3dAddGroupNode},
		{"AddModelNode", li_h3dAddModelNode},
		{"SetupModelAnimStage", li_h3dSetupModelAnimStage},
		{"SetModelAnimParams", li_h3dSetModelAnimParams},
		{"SetModelMorpher", li_h3dSetModelMorpher},
		{"AddMeshNode", li_h3dAddMeshNode},
		{"AddJointNode", li_h3dAddJointNode},
		{"AddLightNode", li_h3dAddLightNode},
		{"AddCameraNode", li_h3dAddCameraNode},
		{"SetupCameraView", li_h3dSetupCameraView},
		{"AddEmitterNode", li_h3dAddEmitterNode},
		{"AdvanceEmitterTime", li_h3dAdvanceEmitterTime},
		{"HasEmitterFinished", li_h3dHasEmitterFinished},
		{"DoNothing", li_h3dDoNothing},
		{NULL, NULL}  /* sentinel */
    };
	
    // dump them into said table
    luaL_register(L, NULL, mylib);
	
	// push the root node
	pushH3DNode(L, H3DRootNode);
	lua_setfield(L, -2, "RootNode");

	// push null node
	pushH3DNode(L, 0);
	lua_setfield(L, -2, "NullNode");

	// push null resource
	pushH3DRes(L, 0);
	lua_setfield(L, -2, "NullRes");
	
	// push enums
	H3DLuaBindings::pushH3dEnums(L);
}

void makeTable(lua_State* L, const char* tabName)
{
	lua_newtable(L);
	lua_setfield(L, -2, tabName);
	lua_getfield(L, -1, tabName);
}

void setVal(lua_State* L, const char* valName, int val)
{
	lua_pushinteger(L, val);
	lua_setfield(L, -2, valName);
}

void pushH3DNode(lua_State* L, H3DNode n)
{
	H3DNode* temp = (H3DNode*)lua_newuserdata(L, sizeof(H3DNode));
	*temp = n;
}

void pushH3DRes(lua_State* L, H3DRes n)
{
	H3DRes* temp = (H3DRes*)lua_newuserdata(L, sizeof(H3DRes));
	*temp = n;
}

inline H3DNode unboxH3DNode(lua_State* L, int pos)
{
	if(!lua_isuserdata(L, pos))
	{
		LOG(logERROR) << "UnboxH3DNode failure: arg is not user data!";
		return 0;
	}
	else
	{
		H3DNode* temp = (H3DNode*)lua_touserdata(L, pos);
		return *temp;
	}
}

inline H3DRes unboxH3DRes(lua_State* L, int pos)
{
	if(!lua_isuserdata(L, pos))
	{
		LOG(logERROR) << "UnboxH3DRes failure: arg is not user data!";
		return 0;
	}
	else
	{
		H3DRes* temp = (H3DRes*)lua_touserdata(L, pos);
		return *temp;
	}
}

void H3DLuaBindings::pushH3dEnums(lua_State* L)
{
	makeTable(L, "H3DOptions");
	setVal(L,  "MaxLogLevel", (int)(H3DOptions::MaxLogLevel));
	setVal(L,  "MaxNumMessages", (int)(H3DOptions::MaxNumMessages));
	setVal(L,  "TrilinearFiltering", (int)(H3DOptions::TrilinearFiltering));
	setVal(L,  "MaxAnisotropy", (int)(H3DOptions::MaxAnisotropy));
	setVal(L,  "TexCompression", (int)(H3DOptions::TexCompression));
	setVal(L,  "SRGBLinearization", (int)(H3DOptions::SRGBLinearization));
	setVal(L,  "LoadTextures", (int)(H3DOptions::LoadTextures));
	setVal(L,  "FastAnimation", (int)(H3DOptions::FastAnimation));
	setVal(L,  "ShadowMapSize", (int)(H3DOptions::ShadowMapSize));
	setVal(L,  "SampleCount", (int)(H3DOptions::SampleCount));
	setVal(L,  "WireframeMode", (int)(H3DOptions::WireframeMode));
	setVal(L,  "DebugViewMode", (int)(H3DOptions::DebugViewMode));
	setVal(L,  "DumpFailedShaders", (int)(H3DOptions::DumpFailedShaders));
	setVal(L,  "GatherTimeStats", (int)(H3DOptions::GatherTimeStats));
	lua_settop(L,-2);
	makeTable(L, "H3DStats");
	setVal(L,  "TriCount", (int)(H3DStats::TriCount));
	setVal(L,  "BatchCount", (int)(H3DStats::BatchCount));
	setVal(L,  "LightPassCount", (int)(H3DStats::LightPassCount));
	setVal(L,  "FrameTime", (int)(H3DStats::FrameTime));
	setVal(L,  "AnimationTime", (int)(H3DStats::AnimationTime));
	setVal(L,  "GeoUpdateTime", (int)(H3DStats::GeoUpdateTime));
	setVal(L,  "ParticleSimTime", (int)(H3DStats::ParticleSimTime));
	setVal(L,  "DefLightsGPUTime", (int)(H3DStats::DefLightsGPUTime));
	setVal(L,  "ParticleGPUTime", (int)(H3DStats::ParticleGPUTime));
	setVal(L,  "TextureVMem", (int)(H3DStats::TextureVMem));
	setVal(L,  "GeometryVMem", (int)(H3DStats::GeometryVMem));
	lua_settop(L,-2);
	makeTable(L, "H3DResTypes");
	setVal(L,  "Undefined", (int)(H3DResTypes::Undefined));
	setVal(L,  "SceneGraph", (int)(H3DResTypes::SceneGraph));
	setVal(L,  "Geometry", (int)(H3DResTypes::Geometry));
	setVal(L,  "Animation", (int)(H3DResTypes::Animation));
	setVal(L,  "Material", (int)(H3DResTypes::Material));
	setVal(L,  "Code", (int)(H3DResTypes::Code));
	setVal(L,  "Shader", (int)(H3DResTypes::Shader));
	setVal(L,  "Texture", (int)(H3DResTypes::Texture));
	setVal(L,  "ParticleEffect", (int)(H3DResTypes::ParticleEffect));
	setVal(L,  "Pipeline", (int)(H3DResTypes::Pipeline));
	lua_settop(L,-2);
	makeTable(L, "H3DResFlags");
	setVal(L,  "NoQuery", (int)(H3DResFlags::NoQuery));
	setVal(L,  "NoTexCompression", (int)(H3DResFlags::NoTexCompression));
	setVal(L,  "NoTexMipmaps", (int)(H3DResFlags::NoTexMipmaps));
	setVal(L,  "TexCubemap", (int)(H3DResFlags::TexCubemap));
	setVal(L,  "TexDynamic", (int)(H3DResFlags::TexDynamic));
	setVal(L,  "TexRenderable", (int)(H3DResFlags::TexRenderable));
	setVal(L,  "TexSRGB", (int)(H3DResFlags::TexSRGB));
	lua_settop(L,-2);
	makeTable(L, "H3DFormats");
	setVal(L,  "Unknown", (int)(H3DFormats::Unknown));
	setVal(L,  "TEX_BGRA8", (int)(H3DFormats::TEX_BGRA8));
	setVal(L,  "TEX_DXT1", (int)(H3DFormats::TEX_DXT1));
	setVal(L,  "TEX_DXT3", (int)(H3DFormats::TEX_DXT3));
	setVal(L,  "TEX_DXT5", (int)(H3DFormats::TEX_DXT5));
	setVal(L,  "TEX_RGBA16F", (int)(H3DFormats::TEX_RGBA16F));
	setVal(L,  "TEX_RGBA32F", (int)(H3DFormats::TEX_RGBA32F));
	lua_settop(L,-2);
	makeTable(L, "H3DGeoRes");
	setVal(L,  "GeometryElem", (int)(H3DGeoRes::GeometryElem));
	setVal(L,  "GeoIndexCountI", (int)(H3DGeoRes::GeoIndexCountI));
	setVal(L,  "GeoVertexCountI", (int)(H3DGeoRes::GeoVertexCountI));
	setVal(L,  "GeoIndices16I", (int)(H3DGeoRes::GeoIndices16I));
	setVal(L,  "GeoIndexStream", (int)(H3DGeoRes::GeoIndexStream));
	setVal(L,  "GeoVertPosStream", (int)(H3DGeoRes::GeoVertPosStream));
	setVal(L,  "GeoVertTanStream", (int)(H3DGeoRes::GeoVertTanStream));
	setVal(L,  "GeoVertStaticStream", (int)(H3DGeoRes::GeoVertStaticStream));
	lua_settop(L,-2);
	makeTable(L, "H3DAnimRes");
	setVal(L,  "EntityElem", (int)(H3DAnimRes::EntityElem));
	setVal(L,  "EntFrameCountI", (int)(H3DAnimRes::EntFrameCountI));
	lua_settop(L,-2);
	makeTable(L, "H3DMatRes");
	setVal(L,  "MaterialElem", (int)(H3DMatRes::MaterialElem));
	setVal(L,  "SamplerElem", (int)(H3DMatRes::SamplerElem));
	setVal(L,  "UniformElem", (int)(H3DMatRes::UniformElem));
	setVal(L,  "MatClassStr", (int)(H3DMatRes::MatClassStr));
	setVal(L,  "MatLinkI", (int)(H3DMatRes::MatLinkI));
	setVal(L,  "MatShaderI", (int)(H3DMatRes::MatShaderI));
	setVal(L,  "SampNameStr", (int)(H3DMatRes::SampNameStr));
	setVal(L,  "SampTexResI", (int)(H3DMatRes::SampTexResI));
	setVal(L,  "UnifNameStr", (int)(H3DMatRes::UnifNameStr));
	setVal(L,  "UnifValueF4", (int)(H3DMatRes::UnifValueF4));
	lua_settop(L,-2);
	makeTable(L, "H3DShaderRes");
	setVal(L,  "ContextElem", (int)(H3DShaderRes::ContextElem));
	setVal(L,  "SamplerElem", (int)(H3DShaderRes::SamplerElem));
	setVal(L,  "UniformElem", (int)(H3DShaderRes::UniformElem));
	setVal(L,  "ContNameStr", (int)(H3DShaderRes::ContNameStr));
	setVal(L,  "SampNameStr", (int)(H3DShaderRes::SampNameStr));
	setVal(L,  "UnifNameStr", (int)(H3DShaderRes::UnifNameStr));
	setVal(L,  "UnifSizeI", (int)(H3DShaderRes::UnifSizeI));
	setVal(L,  "UnifDefValueF4", (int)(H3DShaderRes::UnifDefValueF4));
	lua_settop(L,-2);
	makeTable(L, "H3DTexRes");
	setVal(L,  "TextureElem", (int)(H3DTexRes::TextureElem));
	setVal(L,  "ImageElem", (int)(H3DTexRes::ImageElem));
	setVal(L,  "TexFormatI", (int)(H3DTexRes::TexFormatI));
	setVal(L,  "TexSliceCountI", (int)(H3DTexRes::TexSliceCountI));
	setVal(L,  "ImgWidthI", (int)(H3DTexRes::ImgWidthI));
	setVal(L,  "ImgHeightI", (int)(H3DTexRes::ImgHeightI));
	setVal(L,  "ImgPixelStream", (int)(H3DTexRes::ImgPixelStream));
	lua_settop(L,-2);
	makeTable(L, "H3DPartEffRes");
	setVal(L,  "ParticleElem", (int)(H3DPartEffRes::ParticleElem));
	setVal(L,  "ChanMoveVelElem", (int)(H3DPartEffRes::ChanMoveVelElem));
	setVal(L,  "ChanRotVelElem", (int)(H3DPartEffRes::ChanRotVelElem));
	setVal(L,  "ChanSizeElem", (int)(H3DPartEffRes::ChanSizeElem));
	setVal(L,  "ChanColRElem", (int)(H3DPartEffRes::ChanColRElem));
	setVal(L,  "ChanColGElem", (int)(H3DPartEffRes::ChanColGElem));
	setVal(L,  "ChanColBElem", (int)(H3DPartEffRes::ChanColBElem));
	setVal(L,  "ChanColAElem", (int)(H3DPartEffRes::ChanColAElem));
	setVal(L,  "PartLifeMinF", (int)(H3DPartEffRes::PartLifeMinF));
	setVal(L,  "PartLifeMaxF", (int)(H3DPartEffRes::PartLifeMaxF));
	setVal(L,  "ChanStartMinF", (int)(H3DPartEffRes::ChanStartMinF));
	setVal(L,  "ChanStartMaxF", (int)(H3DPartEffRes::ChanStartMaxF));
	setVal(L,  "ChanEndRateF", (int)(H3DPartEffRes::ChanEndRateF));
	setVal(L,  "ChanDragElem", (int)(H3DPartEffRes::ChanDragElem));
	lua_settop(L,-2);
	makeTable(L, "H3DPipeRes");
	setVal(L,  "StageElem", (int)(H3DPipeRes::StageElem));
	setVal(L,  "StageNameStr", (int)(H3DPipeRes::StageNameStr));
	setVal(L,  "StageActivationI", (int)(H3DPipeRes::StageActivationI));
	lua_settop(L,-2);
	makeTable(L, "H3DNodeTypes");
	setVal(L,  "Undefined", (int)(H3DNodeTypes::Undefined));
	setVal(L,  "Group", (int)(H3DNodeTypes::Group));
	setVal(L,  "Model", (int)(H3DNodeTypes::Model));
	setVal(L,  "Mesh", (int)(H3DNodeTypes::Mesh));
	setVal(L,  "Joint", (int)(H3DNodeTypes::Joint));
	setVal(L,  "Light", (int)(H3DNodeTypes::Light));
	setVal(L,  "Camera", (int)(H3DNodeTypes::Camera));
	setVal(L,  "Emitter", (int)(H3DNodeTypes::Emitter));
	lua_settop(L,-2);
	makeTable(L, "H3DNodeParams");
	setVal(L,  "NameStr", (int)(H3DNodeParams::NameStr));
	setVal(L,  "AttachmentStr", (int)(H3DNodeParams::AttachmentStr));
	lua_settop(L,-2);
	makeTable(L, "H3DModel");
	setVal(L,  "GeoResI", (int)(H3DModel::GeoResI));
	setVal(L,  "SWSkinningI", (int)(H3DModel::SWSkinningI));
	setVal(L,  "LodDist1F", (int)(H3DModel::LodDist1F));
	setVal(L,  "LodDist2F", (int)(H3DModel::LodDist2F));
	setVal(L,  "LodDist3F", (int)(H3DModel::LodDist3F));
	setVal(L,  "LodDist4F", (int)(H3DModel::LodDist4F));
	lua_settop(L,-2);
	makeTable(L, "H3DMesh");
	setVal(L,  "MatResI", (int)(H3DMesh::MatResI));
	setVal(L,  "BatchStartI", (int)(H3DMesh::BatchStartI));
	setVal(L,  "BatchCountI", (int)(H3DMesh::BatchCountI));
	setVal(L,  "VertRStartI", (int)(H3DMesh::VertRStartI));
	setVal(L,  "VertREndI", (int)(H3DMesh::VertREndI));
	setVal(L,  "LodLevelI", (int)(H3DMesh::LodLevelI));
	lua_settop(L,-2);
	makeTable(L, "H3DJoint");
	setVal(L,  "JointIndexI", (int)(H3DJoint::JointIndexI));
	lua_settop(L,-2);
	makeTable(L, "H3DLight");
	setVal(L,  "MatResI", (int)(H3DLight::MatResI));
	setVal(L,  "RadiusF", (int)(H3DLight::RadiusF));
	setVal(L,  "FovF", (int)(H3DLight::FovF));
	setVal(L,  "ColorF3", (int)(H3DLight::ColorF3));
	setVal(L,  "ColorMultiplierF", (int)(H3DLight::ColorMultiplierF));
	setVal(L,  "ShadowMapCountI", (int)(H3DLight::ShadowMapCountI));
	setVal(L,  "ShadowSplitLambdaF", (int)(H3DLight::ShadowSplitLambdaF));
	setVal(L,  "ShadowMapBiasF", (int)(H3DLight::ShadowMapBiasF));
	setVal(L,  "LightingContextStr", (int)(H3DLight::LightingContextStr));
	setVal(L,  "ShadowContextStr", (int)(H3DLight::ShadowContextStr));
	lua_settop(L,-2);
	makeTable(L, "H3DCamera");
	setVal(L,  "PipeResI", (int)(H3DCamera::PipeResI));
	setVal(L,  "OutTexResI", (int)(H3DCamera::OutTexResI));
	setVal(L,  "OutBufIndexI", (int)(H3DCamera::OutBufIndexI));
	setVal(L,  "LeftPlaneF", (int)(H3DCamera::LeftPlaneF));
	setVal(L,  "RightPlaneF", (int)(H3DCamera::RightPlaneF));
	setVal(L,  "BottomPlaneF", (int)(H3DCamera::BottomPlaneF));
	setVal(L,  "TopPlaneF", (int)(H3DCamera::TopPlaneF));
	setVal(L,  "NearPlaneF", (int)(H3DCamera::NearPlaneF));
	setVal(L,  "FarPlaneF", (int)(H3DCamera::FarPlaneF));
	setVal(L,  "OrthoI", (int)(H3DCamera::OrthoI));
	setVal(L,  "OccCullingI", (int)(H3DCamera::OccCullingI));
	lua_settop(L,-2);
	makeTable(L, "H3DEmitter");
	setVal(L,  "MatResI", (int)(H3DEmitter::MatResI));
	setVal(L,  "PartEffResI", (int)(H3DEmitter::PartEffResI));
	setVal(L,  "MaxCountI", (int)(H3DEmitter::MaxCountI));
	setVal(L,  "RespawnCountI", (int)(H3DEmitter::RespawnCountI));
	setVal(L,  "DelayF", (int)(H3DEmitter::DelayF));
	setVal(L,  "EmissionRateF", (int)(H3DEmitter::EmissionRateF));
	setVal(L,  "SpreadAngleF", (int)(H3DEmitter::SpreadAngleF));
	setVal(L,  "ForceF3", (int)(H3DEmitter::ForceF3));
	lua_settop(L,-2);
}

// Manually written functions: (do not overwrite unless you are sure)
int H3DLuaBindings::li_h3dutDumpMessages(lua_State* L)
{
	h3dutDumpMessages();
	return 0;
}


// Paste these into the cpp:
// Automatically generated functions.
int H3DLuaBindings::li_h3dSetNodeTransform(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	float a2 = (float)lua_tonumber(L, 3);
	float a3 = (float)lua_tonumber(L, 4);
	float a4 = (float)lua_tonumber(L, 5);
	float a5 = (float)lua_tonumber(L, 6);
	float a6 = (float)lua_tonumber(L, 7);
	float a7 = (float)lua_tonumber(L, 8);
	float a8 = (float)lua_tonumber(L, 9);
	float a9 = (float)lua_tonumber(L, 10);
	float a10 = (float)lua_tonumber(L, 11);
	h3dSetNodeTransform(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
	
	return 0;
}


int H3DLuaBindings::li_h3dGetVersionString(lua_State* L)
{
	const char* ret = h3dGetVersionString();
	lua_pushstring(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dCheckExtension(lua_State* L)
{
	const char* a1 = getSafeLuaString(L, 2);
	bool ret = h3dCheckExtension(a1);
	lua_pushboolean(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dGetError(lua_State* L)
{
	bool ret = h3dGetError();
	lua_pushboolean(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dInit(lua_State* L)
{
	bool ret = h3dInit();
	lua_pushboolean(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dRelease(lua_State* L)
{
	h3dRelease();
	
	return 0;
}


int H3DLuaBindings::li_h3dSetupViewport(lua_State* L)
{
	int a1 = (int)lua_tointeger(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	int a4 = (int)lua_tointeger(L, 5);
	bool a5 = (lua_toboolean(L, 6) > 0);
	h3dSetupViewport(a1, a2, a3, a4, a5);
	
	return 0;
}


int H3DLuaBindings::li_h3dRender(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	h3dRender(a1);
	
	return 0;
}


int H3DLuaBindings::li_h3dFinalizeFrame(lua_State* L)
{
	h3dFinalizeFrame();
	
	return 0;
}


int H3DLuaBindings::li_h3dClear(lua_State* L)
{
	h3dClear();
	
	return 0;
}


int H3DLuaBindings::li_h3dShowOverlay(lua_State* L)
{
	// Inserted fix for SVN change to an array of quads
	// (Only supports one quad, but H3D can take multiple)
	float arr[16];
	for (int i = 0; i < 16; ++i)
	{
		arr[i] = (float)lua_tonumber(L, i+2);
	}

	float a17 = (float)lua_tonumber(L, 18);
	float a18 = (float)lua_tonumber(L, 19);
	float a19 = (float)lua_tonumber(L, 20);
	float a20 = (float)lua_tonumber(L, 21);
	H3DRes a21 = unboxH3DRes(L, 22);
	int a22 = (int)lua_tointeger(L, 23);
	h3dShowOverlays(arr, 4, a17, a18, a19, a20, a21, a22);
	
	return 0;
} 

int H3DLuaBindings::li_h3dDoNothing(lua_State* L)
{
	return 0;
}


int H3DLuaBindings::li_h3dClearOverlays(lua_State* L)
{
	h3dClearOverlays();
	
	return 0;
}


int H3DLuaBindings::li_h3dGetResType(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	int ret = h3dGetResType(a1);
	lua_pushinteger(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dGetResName(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	const char* ret = h3dGetResName(a1);
	lua_pushstring(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dGetNextResource(lua_State* L)
{
	int a1 = (int)lua_tointeger(L, 2);
	H3DRes a2 = unboxH3DRes(L, 3);
	H3DRes ret = h3dGetNextResource(a1, a2);
	pushH3DRes(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dFindResource(lua_State* L)
{
	int a1 = (int)lua_tointeger(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	H3DRes ret = h3dFindResource(a1, a2);
	pushH3DRes(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dAddResource(lua_State* L)
{
	int a1 = (int)lua_tointeger(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	H3DRes ret = h3dAddResource(a1, a2, a3);
	pushH3DRes(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dCloneResource(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	H3DRes ret = h3dCloneResource(a1, a2);
	pushH3DRes(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dRemoveResource(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	int ret = h3dRemoveResource(a1);
	lua_pushinteger(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dIsResLoaded(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	bool ret = h3dIsResLoaded(a1);
	lua_pushboolean(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dUnloadResource(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	h3dUnloadResource(a1);
	
	return 0;
}


int H3DLuaBindings::li_h3dGetResElemCount(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int ret = h3dGetResElemCount(a1, a2);
	lua_pushinteger(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dFindResElem(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	const char* a4 = getSafeLuaString(L, 5);
	int ret = h3dFindResElem(a1, a2, a3, a4);
	lua_pushinteger(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dGetResParamI(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	int a4 = (int)lua_tointeger(L, 5);
	int ret = h3dGetResParamI(a1, a2, a3, a4);
	lua_pushinteger(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dSetResParamI(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	int a4 = (int)lua_tointeger(L, 5);
	int a5 = (int)lua_tointeger(L, 6);
	h3dSetResParamI(a1, a2, a3, a4, a5);
	
	return 0;
}


int H3DLuaBindings::li_h3dGetResParamF(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	int a4 = (int)lua_tointeger(L, 5);
	int a5 = (int)lua_tointeger(L, 6);
	float ret = h3dGetResParamF(a1, a2, a3, a4, a5);
	lua_pushnumber(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dSetResParamF(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	int a4 = (int)lua_tointeger(L, 5);
	int a5 = (int)lua_tointeger(L, 6);
	float a6 = (float)lua_tonumber(L, 7);
	h3dSetResParamF(a1, a2, a3, a4, a5, a6);
	
	return 0;
}


int H3DLuaBindings::li_h3dGetResParamStr(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	int a4 = (int)lua_tointeger(L, 5);
	const char* ret = h3dGetResParamStr(a1, a2, a3, a4);
	lua_pushstring(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dSetResParamStr(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	int a4 = (int)lua_tointeger(L, 5);
	const char* a5 = getSafeLuaString(L, 6);
	h3dSetResParamStr(a1, a2, a3, a4, a5);
	
	return 0;
}


int H3DLuaBindings::li_h3dQueryUnloadedResource(lua_State* L)
{
	int a1 = (int)lua_tointeger(L, 2);
	H3DRes ret = h3dQueryUnloadedResource(a1);
	pushH3DRes(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dReleaseUnusedResources(lua_State* L)
{
	h3dReleaseUnusedResources();
	
	return 0;
}


int H3DLuaBindings::li_h3dCreateTexture(lua_State* L)
{
	const char* a1 = getSafeLuaString(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	int a4 = (int)lua_tointeger(L, 5);
	int a5 = (int)lua_tointeger(L, 6);
	H3DRes ret = h3dCreateTexture(a1, a2, a3, a4, a5);
	pushH3DRes(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dSetShaderPreambles(lua_State* L)
{
	const char* a1 = getSafeLuaString(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	h3dSetShaderPreambles(a1, a2);
	
	return 0;
}


int H3DLuaBindings::li_h3dSetMaterialUniform(lua_State* L)
{
	H3DRes a1 = unboxH3DRes(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	float a3 = (float)lua_tonumber(L, 4);
	float a4 = (float)lua_tonumber(L, 5);
	float a5 = (float)lua_tonumber(L, 6);
	float a6 = (float)lua_tonumber(L, 7);
	bool ret = h3dSetMaterialUniform(a1, a2, a3, a4, a5, a6);
	lua_pushboolean(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dGetNodeType(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	int ret = h3dGetNodeType(a1);
	lua_pushinteger(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dGetNodeParent(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	H3DNode ret = h3dGetNodeParent(a1);
	pushH3DNode(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dSetNodeParent(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	H3DNode a2 = unboxH3DNode(L, 3);
	bool ret = h3dSetNodeParent(a1, a2);
	lua_pushboolean(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dGetNodeChild(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	H3DNode ret = h3dGetNodeChild(a1, a2);
	pushH3DNode(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dAddNodes(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	H3DRes a2 = unboxH3DRes(L, 3);
	H3DNode ret = h3dAddNodes(a1, a2);
	pushH3DNode(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dRemoveNode(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	h3dRemoveNode(a1);
	
	return 0;
}


int H3DLuaBindings::li_h3dSetNodeActivation(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	bool a2 = (bool)(lua_toboolean(L, 3) > 0);
	h3dSetNodeActivation(a1, a2);
	
	return 0;
}


int H3DLuaBindings::li_h3dCheckNodeTransFlag(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	bool a2 = (bool)(lua_toboolean(L, 3) > 0);
	bool ret = h3dCheckNodeTransFlag(a1, a2);
	lua_pushboolean(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dGetNodeParamI(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int ret = h3dGetNodeParamI(a1, a2);
	lua_pushinteger(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dSetNodeParamI(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	h3dSetNodeParamI(a1, a2, a3);
	
	return 0;
}


int H3DLuaBindings::li_h3dGetNodeParamF(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	float ret = h3dGetNodeParamF(a1, a2, a3);
	lua_pushnumber(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dSetNodeParamF(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	float a4 = (float)lua_tonumber(L, 5);
	h3dSetNodeParamF(a1, a2, a3, a4);
	
	return 0;
}


int H3DLuaBindings::li_h3dGetNodeParamStr(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	const char* ret = h3dGetNodeParamStr(a1, a2);
	lua_pushstring(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dSetNodeParamStr(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	const char* a3 = getSafeLuaString(L, 4);
	h3dSetNodeParamStr(a1, a2, a3);
	
	return 0;
}


int H3DLuaBindings::li_h3dFindNodes(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	int ret = h3dFindNodes(a1, a2, a3);
	lua_pushinteger(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dGetNodeFindResult(lua_State* L)
{
	int a1 = (int)lua_tointeger(L, 2);
	H3DNode ret = h3dGetNodeFindResult(a1);
	pushH3DNode(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dCastRay(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	float a2 = (float)lua_tonumber(L, 3);
	float a3 = (float)lua_tonumber(L, 4);
	float a4 = (float)lua_tonumber(L, 5);
	float a5 = (float)lua_tonumber(L, 6);
	float a6 = (float)lua_tonumber(L, 7);
	float a7 = (float)lua_tonumber(L, 8);
	int a8 = (int)lua_tointeger(L, 9);
	int ret = h3dCastRay(a1, a2, a3, a4, a5, a6, a7, a8);
	lua_pushinteger(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dCheckNodeVisibility(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	H3DNode a2 = unboxH3DNode(L, 3);
	bool a3 = (bool)(lua_toboolean(L, 4) > 0);
	bool a4 = (bool)(lua_toboolean(L, 5) > 0);
	int ret = h3dCheckNodeVisibility(a1, a2, a3, a4);
	lua_pushinteger(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dAddGroupNode(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	H3DNode ret = h3dAddGroupNode(a1, a2);
	pushH3DNode(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dAddModelNode(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	H3DRes a3 = unboxH3DRes(L, 4);
	H3DNode ret = h3dAddModelNode(a1, a2, a3);
	pushH3DNode(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dSetupModelAnimStage(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	H3DRes a3 = unboxH3DRes(L, 4);
	int a4 = (int)lua_tointeger(L, 5);
	const char* a5 = getSafeLuaString(L, 6);
	bool a6 = (bool)(lua_toboolean(L, 7) > 0);
	h3dSetupModelAnimStage(a1, a2, a3, a4, a5, a6);
	
	return 0;
}


int H3DLuaBindings::li_h3dSetModelAnimParams(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	float a3 = (float)lua_tonumber(L, 4);
	float a4 = (float)lua_tonumber(L, 5);
	h3dSetModelAnimParams(a1, a2, a3, a4);
	
	return 0;
}


int H3DLuaBindings::li_h3dSetModelMorpher(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	float a3 = (float)lua_tonumber(L, 4);
	bool ret = h3dSetModelMorpher(a1, a2, a3);
	lua_pushboolean(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dAddMeshNode(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	H3DRes a3 = unboxH3DRes(L, 4);
	int a4 = (int)lua_tointeger(L, 5);
	int a5 = (int)lua_tointeger(L, 6);
	int a6 = (int)lua_tointeger(L, 7);
	int a7 = (int)lua_tointeger(L, 8);
	H3DNode ret = h3dAddMeshNode(a1, a2, a3, a4, a5, a6, a7);
	pushH3DNode(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dAddJointNode(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	H3DNode ret = h3dAddJointNode(a1, a2, a3);
	pushH3DNode(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dAddLightNode(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	H3DRes a3 = unboxH3DRes(L, 4);
	const char* a4 = getSafeLuaString(L, 5);
	const char* a5 = getSafeLuaString(L, 6);
	H3DNode ret = h3dAddLightNode(a1, a2, a3, a4, a5);
	pushH3DNode(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dAddCameraNode(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	H3DRes a3 = unboxH3DRes(L, 4);
	H3DNode ret = h3dAddCameraNode(a1, a2, a3);
	pushH3DNode(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dSetupCameraView(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	float a2 = (float)lua_tonumber(L, 3);
	float a3 = (float)lua_tonumber(L, 4);
	float a4 = (float)lua_tonumber(L, 5);
	float a5 = (float)lua_tonumber(L, 6);
	h3dSetupCameraView(a1, a2, a3, a4, a5);
	
	return 0;
}


int H3DLuaBindings::li_h3dAddEmitterNode(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	const char* a2 = getSafeLuaString(L, 3);
	H3DRes a3 = unboxH3DRes(L, 4);
	H3DRes a4 = unboxH3DRes(L, 5);
	int a5 = (int)lua_tointeger(L, 6);
	int a6 = (int)lua_tointeger(L, 7);
	H3DNode ret = h3dAddEmitterNode(a1, a2, a3, a4, a5, a6);
	pushH3DNode(L, ret);
	return 1;
}


int H3DLuaBindings::li_h3dAdvanceEmitterTime(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	float a2 = (float)lua_tonumber(L, 3);
	h3dAdvanceEmitterTime(a1, a2);
	
	return 0;
}


int H3DLuaBindings::li_h3dHasEmitterFinished(lua_State* L)
{
	H3DNode a1 = unboxH3DNode(L, 2);
	bool ret = h3dHasEmitterFinished(a1);
	lua_pushboolean(L, ret);
	return 1;
}
